#include "widget.h"
#include "ui_widget.h"
#include <QTextStream>
#include <QFileDialog>

void myBtnSave();
void myBtnSaveAs();

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    // 虽然上面一行代码进行 widget 和 ui 的窗口关联，但是如果发生窗体大小变化的时候，里面的控件不会随之变化
    // 通过下面这行代码进行显示说明，让窗口变化的时候，布局随之一同变化调整
    this->setLayout(ui->verticalLayout);
    ui->widgetBottom->setLayout(ui->horizontalLayout_2);
    // QObject::connect(sender, SIGNAL(signal()), receiver, SLOT(slot()));
    this->setWindowTitle("记事本");
    ui->textEdit->installEventFilter(this);


    QObject::connect(ui->btnOpen, SIGNAL(clicked()), this, SLOT(handleBtnOpenClicked()));

    QObject::connect(ui->btnSave, &QPushButton::clicked, this, [=](){
        on_btnSave_clicked();
        // handleMysignal(100);
    });

    QObject::connect(ui->btnClose, &QPushButton::clicked, this, &Widget::handleBtnCloseClicked);

    QObject::connect(ui->textEdit, &QTextEdit::textChanged, this, &Widget::contextChanged);

    QObject::connect(ui->textEdit, &QTextEdit::cursorPositionChanged, this, &Widget::handleCursorPositionChanged);

    // QObject::connect(this, SIGNAL(mysignal(int)), this, SLOT(handleMysignal(int)));

    QShortcut *shortcutOpen    = new QShortcut(QKeySequence(tr("Ctrl+O", "File|Open")), this);
    QShortcut *shortcutSave    = new QShortcut(QKeySequence(tr("Ctrl+S", "File|Save")), this);
    QShortcut *shortcutZoomIn  = new QShortcut(QKeySequence(tr("Ctrl+Alt+Right", "File|Magnify")), this);
    QShortcut *shortcutZoomOut = new QShortcut(QKeySequence(tr("Ctrl+Alt+Left", "File|Magnify")), this);
    QShortcut *shortcutZoomdef = new QShortcut(QKeySequence(tr("Ctrl+0", "File|defaultFontSize")), this);
    QShortcut *shortcutCheck   = new QShortcut(QKeySequence(tr("Ctrl+F", "File|checkText")), this);

    // QObject::connect(shortcutOpen, &QShortcut::activated, [this](){
    //     Widget::handleBtnOpenClicked();
    // });

    // QObject::connect(shortcutSave, &QShortcut::activated, [this](){
    //     Widget::on_btnSave_clicked();
    // });

    // 或者用 QShortcut 直接绑定 slot这样实现
    QObject::connect(shortcutOpen,    &QShortcut::activated, this, &Widget::handleBtnOpenClicked);
    QObject::connect(shortcutSave,    &QShortcut::activated, this, &Widget::on_btnSave_clicked);
    QObject::connect(shortcutZoomIn,  &QShortcut::activated, this, &Widget::handleShortcutZoomIn);
    QObject::connect(shortcutZoomOut, &QShortcut::activated, this, &Widget::handleShortcutZoomOut);
    QObject::connect(shortcutZoomdef, &QShortcut::activated, this, &Widget::handleShortcutZoomdef);
    QObject::connect(shortcutCheck,   &QShortcut::activated, this, &Widget::handleShortcutCheck);


    findDlg = new QDialog(this);
    findDlg->setWindowTitle(tr("查找"));
    findLineEdit = new QLineEdit(findDlg);

    QPushButton *btnFindNext = new QPushButton(tr("查找下一个"), findDlg);
    QVBoxLayout *layout = new QVBoxLayout(findDlg);

    layout->addWidget(findLineEdit);
    layout->addWidget(btnFindNext);

    // connect(btnFindNext, SIGNAL(callDialogFind(QString)), this, SLOT(Widget::showFindText(QString selectedText)));
    QObject::connect(this, &Widget::callDialogFind, this, &Widget::showFindText);
    QObject::connect(btnFindNext, &QPushButton::clicked, this, &Widget::handleBtnfindNext);
}

Widget::~Widget()
{
    delete ui;
}

bool Widget::eventFilter(QObject *obj, QEvent *event)
{
    if (obj == ui->textEdit) {
        if (event->type() == QEvent::KeyPress) {
            QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
            if(!ui->textEdit) return false;
            if(keyEvent->modifiers() == Qt::ControlModifier && keyEvent->key() == Qt::Key_D)
            {
                QTextCursor cursor = ui->textEdit->textCursor();
                QString currentLineText = ui->textEdit->textCursor().block().text();
                cursor.movePosition(QTextCursor::EndOfBlock);
                cursor.insertBlock();
                cursor.insertText(currentLineText);
                return true;
            }
            else  return false;
        }
        else  return false;
    }

    return QWidget::eventFilter(obj, event);
}

void Widget::handleBtnOpenClicked()
{
    QString filePath = QFileDialog::getOpenFileName(this, "Open File", "D:/code/Qt_learn/", "Text Files (*.txt);;All Files (*)");
    if(filePath.isEmpty())  return;
    ui->textEdit->clear();

    file.setFileName(filePath);
    if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){
        qDebug() << "Error opening file:" << file.errorString();
        return;
    }

    QTextStream in(&file);
    QString str = ui->comboBox->currentText();
    auto encoding = QStringConverter::encodingForName(str.toUtf8());
    if (encoding) {
        in.setEncoding(*encoding);  //  使用转换后的编码
    } else {
        qDebug() << "Invalid encoding:" << str;  // 处理无效编码情况
    }
    while(!in.atEnd())
    {
        QString context = in.readLine();
        ui->textEdit->append(context);
    }

    file.close();
    QFileInfo fileinfo(filePath);
    QString file_Name = fileinfo.fileName();
    this->setWindowTitle(file_Name + "记事本");
    isTextModified = false;
    currentFilePath = filePath;
    fontDefaultSize = ui->textEdit->font().pointSize();
}

void Widget::handleBtnCloseClicked()
{
    // qDebug() << currentFilePath;
    // qDebug() << isTextModified;
    if (isTextModified) { // 如果内容被修改
        QMessageBox::StandardButton reply;
        reply = QMessageBox::warning(this, "Unsaved Changes",
                                     "You have unsaved changes. Do you want to save them before closing?",
                                     QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);

        if (reply == QMessageBox::Yes) {
            file.setFileName(currentFilePath);
            myBtnSave();
            ui->textEdit->clear(); // 继续关闭
            currentFilePath = "";
            isTextModified = false;
            this->setWindowTitle("记事本");
        } else if (reply == QMessageBox::No) {
            ui->textEdit->clear();
            currentFilePath = ""; // 直接关闭
            isTextModified = false;
            this->setWindowTitle("记事本");
        } else {
            return; // 取消关闭
        }
    } else {
        ui->textEdit->clear();
        currentFilePath = ""; // 没有修改，直接关闭
        isTextModified = false;
        this->setWindowTitle("记事本");
    }
}

// void Widget::handleMysignal(int value)
// {
//     qDebug() << "mySignal: " << value;
// }

void Widget::on_btnSave_clicked()
{
    // qDebug() << currentFilePath;
    if(!currentFilePath.isEmpty())
    {
        myBtnSave();
    }
    else
    {
        myBtnSaveAs();
    }

    isTextModified = false;
}

void Widget::myBtnSave()
{
    if(currentFilePath.isEmpty())
    {
        myBtnSaveAs();
    }

    file.setFileName(currentFilePath);
    if(file.open(QIODevice::WriteOnly | QIODevice::Text))
    {
        QTextStream out(&file);
        out.setEncoding(QStringConverter::Utf8);
        QString context = ui->textEdit->toPlainText();
        out << context;
        file.close();
    }
}

void Widget::myBtnSaveAs()
{
    QString filePath = QFileDialog::getSaveFileName(this, tr("Save file"),
                                                    "../untitled.txt",
                                                    tr("Text Files (*.txt)"));
    if(!filePath.isEmpty())
    {
        currentFilePath = filePath;
        myBtnSave();
    }
}


void Widget::on_comboBox_currentIndexChanged()
{
    ui->textEdit->clear();
    if(!currentFilePath.isNull())
    {
        file.setFileName(currentFilePath);

        if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
            // qDebug() << "Error opening file:" << file.errorString();
            return;
        }
        QTextStream in(&file);
        QString str = ui->comboBox->currentText();
        auto encoding = QStringConverter::encodingForName(str.toUtf8());
        if (encoding) {
            in.setEncoding(*encoding);  //  使用转换后的编码
        }
        file.seek(0);
        while(!in.atEnd())
        {
            QString context = in.readLine();
            ui->textEdit->append(context);
        }
        file.close();
    }
}

void Widget::handleCursorPositionChanged()
{
    QTextCursor cursor = ui->textEdit->textCursor();
    int col = cursor.columnNumber() + 1;
    int row = cursor.blockNumber()  + 1;
    const QString str = "第" + QString::number(row) + "行" + "第" + QString::number(col) + "列";
    ui->labelPosition->setText(str);

    // 设置当前行高亮
    QList<QTextEdit::ExtraSelection> extraSelections;
    QTextEdit::ExtraSelection ext;

    // 1.知道当前行
    ext.cursor = ui->textEdit->textCursor();
    ext.format.setProperty(QTextFormat::FullWidthSelection, true);
    // 2.颜色
    ext.format.setBackground(Qt::lightGray);
    // 3. 设置
    extraSelections.append(ext);
    ui->textEdit->setExtraSelections(extraSelections);
}

void Widget::handleShortcutZoomIn()
{
    // 获得TextEdit的当前信息
    QFont font = ui->textEdit->font();
    // 获得当前字体的大小
    if(font.pointSize() == -1) return;
    int fontSize = font.pointSize();
    // 改变大小，并设置字体大小
    font.setPointSize(++fontSize);
    ui->textEdit->setFont(font);
}

void Widget::handleShortcutZoomOut()
{
    QFont font = ui->textEdit->font();
    if(font.pointSize() == -1) return;
    int fontSize = font.pointSize() - 1;
    font.setPointSize(fontSize);
    ui->textEdit->setFont(font);
}

void Widget::handleShortcutZoomdef()
{
    // qDebug() << "handleShortcutZoomdef has been run";
    if(fontDefaultSize == -1) return;
    QFont font = ui->textEdit->font();
    font.setPointSize(fontDefaultSize);
    ui->textEdit->setFont(font);
}

void Widget::handleShortcutCheck()
{
    QString selectedText = ui->textEdit->textCursor().selectedText();
    qDebug() << selectedText.toStdString();
    emit callDialogFind(selectedText);
}

void Widget::showFindText(QString selectedText)
{
    qDebug() << "findDlg will show";
    findDlg->show();
    findLineEdit->setText(selectedText);
}

void Widget::handleBtnfindNext()
{
    qDebug() << "handleBtnfindNext has been run";
    QTextCursor cursor = ui->textEdit->textCursor();
    QString selectedText = ui->textEdit->textCursor().selectedText();
    if (!cursor.isNull() && !cursor.atEnd())
    {
        qDebug() << "selectedText:" << selectedText << ", " << "col, row:" << cursor.columnNumber() << ", " << cursor.blockNumber();
        cursor = ui->textEdit->document()->find(selectedText, cursor);
        ui->textEdit->setTextCursor(cursor);
        qDebug() << "selectedText:" << selectedText << ", " << "col, row:" << cursor.columnNumber() << ", " << cursor.blockNumber();
    }
    else
    {
        cursor = ui->textEdit->document()->find(selectedText, QTextCursor(ui->textEdit->document()));
        if(!cursor.isNull()){
            ui->textEdit->setTextCursor(cursor);
        }
    }
}
